#include "system.h"

/* MCU时钟频率配置 */
static void system_clock_init(u32 plln, u32 pllm, u32 pllp, u32 pllq)
{
  HAL_StatusTypeDef ret = HAL_OK;
  RCC_OscInitTypeDef RCC_OscInitStructure;
  RCC_ClkInitTypeDef RCC_ClkInitStructure;

  __HAL_RCC_PWR_CLK_ENABLE();

  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
  RCC_OscInitStructure.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStructure.HSEState = RCC_HSE_ON;
  RCC_OscInitStructure.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStructure.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStructure.PLL.PLLM = pllm;
  RCC_OscInitStructure.PLL.PLLN = plln;
  RCC_OscInitStructure.PLL.PLLP = pllp;
  RCC_OscInitStructure.PLL.PLLQ = pllq;
  ret = HAL_RCC_OscConfig(&RCC_OscInitStructure);

  if (ret != HAL_OK)
    while (1);

  ret = HAL_PWREx_EnableOverDrive();
  if (ret != HAL_OK)
    while (1);

  RCC_ClkInitStructure.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 |
                                    RCC_CLOCKTYPE_PCLK2);
  RCC_ClkInitStructure.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStructure.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStructure.APB1CLKDivider = RCC_HCLK_DIV4;
  RCC_ClkInitStructure.APB2CLKDivider = RCC_HCLK_DIV2;
  ret = HAL_RCC_ClockConfig(&RCC_ClkInitStructure, FLASH_LATENCY_5);

  if (ret != HAL_OK)
    while (1);
}


static u32 fac_us = 0;              //us延时倍乘数

//初始化延迟函数
//当使用ucos的时候,此函数会初始化ucos的时钟节拍
//SYSTICK的时钟固定为AHB时钟
//SYSCLK:系统时钟频率
static void system_delay_init(u8 SYSCLK)
{
  HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);//SysTick频率为HCLK
  fac_us = SYSCLK;            //不论是否使用OS,fac_us都需要使用
}

//延时nus
//nus为要延时的us数.	
//nus:0~190887435(最大值即2^32/fac_us@fac_us=22.5)	 
void delay_us(u32 nus)
{
  u32 ticks;
  u32 told, tnow, tcnt = 0;
  u32 reload = SysTick->LOAD;        //LOAD的值
  ticks = nus * fac_us;            //需要的节拍数
  told = SysTick->VAL;                //刚进入时的计数器值
  while (1)
  {
    tnow = SysTick->VAL;
    if (tnow != told)
    {
      if (tnow < told)
        tcnt += told - tnow;  //这里注意一下SYSTICK是一个递减的计数器就可以了.
      else
        tcnt += reload - tnow + told;
      told = tnow;
      if (tcnt >= ticks)
        break;      //时间超过/等于要延迟的时间,则退出.
    }
  }
}

//延时nms
//nms:要延时的ms数
void delay_ms(u16 nms)
{
  u32 i;
  for (i = 0; i < nms; i++)
    delay_us(1000);
}


void system_init(void)
{
  system_clock_init(336, 12, 2, 8);
  system_delay_init(168);
}


#ifdef  USE_FULL_ASSERT
//µ±±ҫ̡ʾ³ö´񡊱º򴋺¯ʽӃÀ´±¨¸洭γµĎļþº͋ùԚА
//file£ºָϲԴ΄¼þ
//line£ºָϲԚ΄¼þ֐µĐЊý
void assert_failed(uint8_t* file, uint32_t line)
{ 
  while (1)
  {
  }
}
#endif

//THUMBָÁ֧³ֻ㱠ĚÁª
//²ɓÈ珂·½·¨ʵϖִА»㱠ָÁI  
__asm void WFI_SET(void)
{
  WFI;
}
//¹رՋùӐ֐¶Ϩµ«ʇ²»°üÀ¨faultº͎MI֐¶ϩ
__asm void INTX_DISABLE(void)
{
  CPSID I
  BX LR
}
//¿ªƴ˹Ӑ֐¶ύ
__asm void INTX_ENABLE(void)
{
  CPSIE I
  BX LR
}
//ɨփջ¶¥µؖ·
//addr:ջ¶¥µؖ·
__asm void MSR_MSP(u32 addr)
{
  MSR MSP, r0      //set Main Stack value
  BX r14
}
